/*
-----------------------------------------------------------------------------
This file is part of NxGraphics, Multimedia Engine.
Author : Stephane Kyles. Developed in Prague, Czech Republic.
		_   __       ______                     __     _            
	   / | / /_  __ / ____/_____ ____ _ ____   / /_   (_)_____ _____
	  /  |/ /| |/_// / __ / ___// __ `// __ \ / __ \ / // ___// ___/
	 / /|  /_>  < / /_/ // /   / /_/ // /_/ // / / // // /__ (__  ) 
	/_/ |_//_/|_| \____//_/    \__,_// .___//_/ /_//_/ \___//____/  
									/_/                             
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-----------------------------------------------------------------------------
*/
#ifndef __NXGRAPHICS3DMANAGER_H__
#define __NXGRAPHICS3DMANAGER_H__

#include "NxGraphics_Prerequisites.h"

namespace NxGraphics_Namespace {

class NxGraphics_Export NxScene3DManager : public Singleton<NxScene3DManager>  
{
	
public:
    //! 3D Scene Manager Constructor, Initializes the Singleton
	NxScene3DManager();
	//! Creates 3D scene from provided project file.
    /*!
      \param FilePath the path of scene to load.
      \param RTarget the Ogre::Rendertexture pointer to render the scene.
	  \param Type the type of 3D projet scene to load.
      \return Shared Pointer
      \sa DeleteNx3DScene
    */
	Nx3DScenePtr CreateNx3DScene( Ogre::String FilePath, Ogre::RenderTexture * RTarget, NxGraphics_3D_Scene_Types Type );
	//! Deletes the provided 3D scene.
    /*!
      \param Scene the scene pointer to delete.
      \sa CreateNx3DScene
    */
	bool DeleteNx3DScene( Nx3D_Scene * Scene );
	//! Get raw 3D scene pointer from index.
    /*!
      \param index the 3D scene index to get.
    */	
	Nx3D_Scene * GetNx3DScene( int index ); 
	//! Get number of 3D scenes owned by the manager.
	size_t GetNumNxScenes();
	//! Get 3DSceneManager Singleton
	static NxScene3DManager& getSingleton(void);
	//! Create the 3D Physics Manager
	void CreatePhysicsManager();
	//! Updates all Scene Physics.
	bool UpdatePhysics( unsigned long elapsedMS );
	//! Deletes the 3D Physics Manager
	void DeletePhysicsManager();
	//! Get Abstract singleton factory class used for instancing objects in the Physics SDK.
	NxPhysicsSDK * GetPhysicsSdk();
	//! Get Skin Width.
	float GetSkinWidth();
	//!Physx Hardware aceeleration Enabled ?
	bool HasPhysxHardwareAcceleration();
	//! Creates Physx Scene with default plane set to level 0.
    /*!
      \return Physx Scene
      \sa DeletePhysicsWorld3D
    */
	NxScene * CreatePhysicsWorld3D();
	//! Deletes a Physx Scene.
    /*!
      \param PhysxScene the Physx scene to delete.
	  \return true if successfull.
    */
	bool DeletePhysicsWorld3D( NxScene * PhysxScene );
	//! Connect to Physx Visual Remote Debugger.
    /*!
      \param IpAddress the ip address to connect
      \return true if successful
    */
	bool DebugPhysics3D( const std::string & TargetIpAddress, int TargetPort = 5425 );
	//! Update Camera Controllers
	bool UpdateControllers();
	//! Get Physx Memory allocator.
	UserAllocator * GetPhysics3DMemoryAllocator();
	//! Get Physx Controller Manager.
	NxControllerManager * GetPhysicsControllerManager();
	//! Get Nx3DScene From Physx Scene.
	Nx3D_Scene * GetNx3DSceneFromPhysxScene( NxScene * Scene );
	//! Get Nx3DScene From Scene Manager.
	Nx3D_Scene * GetNx3DSceneFromOgreSceneManager( Ogre::SceneManager * SceneMgr );



	//! Updates a 2D Physics Scene.
	void UpdatePhysicEngine2D();
	//! Creates 2D Physic world
    /*!
      \param LowerBoundX the lower bound X
      \param LowerBoundY the lower bound Y
	  \param HigherBoundX the higher bound X
	  \param HigherBoundY the higher bound Y
	  \param Gravity the gravity
      \return the physic 2D world
      \sa DeletePhysicsWorld2D
    */
	b2World * CreatePhysicsWorld2D( float LowerBoundX, float LowerBoundY, float HigherBoundX, float HigherBoundY, float Gravity );
	//! Deletes a 2D Physic world
    /*!
      \param World2D the 2D physic world to delete
      \return true is successfull.
      \sa CreatePhysicsWorld2D
    */
	bool DeletePhysicsWorld2D( b2World * World2D );
 
private :
	//! 3D Physics Scene Container.
	std::list< NxScene * > PhysicsWorld3DList;
	//! 3D Physics Scene Container.
	std::list< b2World * > PhysicsWorld2DList;
	//! 3D Scene Container.
	std::list< Nx3D_Scene * > Scene3DList;
	//! Physx Sdk.
	NxPhysicsSDK * physicsSDK;
	//! Physx Hardware Support.
	bool mHardwareSimulation;
	//! 3D Physx memory allocator.
	UserAllocator * PhysicsAllocator;
	//! Physx Controller Manager.
	NxControllerManager * nControllerManager;
	
	
	//boost::mutex initMutex;
	//boost::condition initSync;

};

template<> NxScene3DManager* Singleton<NxScene3DManager>::ms_Singleton = 0;

}//namespace

#endif